/*
Miranda IM for Windows Search

Copyright (C) 2012-2014 Nikolay Raspopov

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#pragma once

#include "MirandaSearch.h"

// CMirandaProtocol

class ATL_NO_VTABLE CMirandaProtocol
	: public CComObjectRootEx< CComMultiThreadModel >
	, public CComCoClass< CMirandaProtocol, &CLSID_MirandaProtocol >
	, public ISearchProtocol2
	, public ISearchProtocolThreadContext
	, public IInternetProtocol
	, public IInternetProtocolInfo
	//, public IShellFolder
	//, public IPersistFolder
	//, public IDelegateFolder
	, public IObjectSafetyImpl< CMirandaProtocol, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA >
{
public:
	CMirandaProtocol();

DECLARE_REGISTRY_RESOURCEID(IDR_MIRANDAPROTOCOL)
DECLARE_PROTECT_FINAL_CONSTRUCT()
DECLARE_GET_CONTROLLING_UNKNOWN()

BEGIN_COM_MAP(CMirandaProtocol)
	COM_INTERFACE_ENTRY2(ISearchProtocol, ISearchProtocol2)
	COM_INTERFACE_ENTRY(ISearchProtocol2)
	COM_INTERFACE_ENTRY(ISearchProtocolThreadContext)
	COM_INTERFACE_ENTRY2(IInternetProtocolRoot, IInternetProtocol)
	COM_INTERFACE_ENTRY(IInternetProtocol)
	COM_INTERFACE_ENTRY(IInternetProtocolInfo)
	//COM_INTERFACE_ENTRY(IShellFolder)
	//COM_INTERFACE_ENTRY2(IPersist, IPersistFolder)
	//COM_INTERFACE_ENTRY(IPersistFolder)
	//COM_INTERFACE_ENTRY(IDelegateFolder)
	COM_INTERFACE_ENTRY(IObjectSafety)
	COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
END_COM_MAP()

BEGIN_CATEGORY_MAP(CMirandaProtocol)
	IMPLEMENTED_CATEGORY(CATID_SafeForScripting)
	IMPLEMENTED_CATEGORY(CATID_SafeForInitializing)
END_CATEGORY_MAP()

	HRESULT FinalConstruct();
	void FinalRelease();

	HRESULT ReadRoot();
	HRESULT ReadContacts();
	HRESULT ReadEvents( const CString& sRelativeURL );
	HRESULT ReadMessage( const CString& sRelativeURL );

protected:
	CComPtr< IUnknown >	m_pUnkMarshaler;
	CStringA			m_sData;			// URL data when accessed as Protocol Handler

	// ISearchProtocol

	STDMETHOD(Init)(TIMEOUT_INFO *pTimeoutInfo, IProtocolHandlerSite *pProtocolHandlerSite, PROXY_INFO *pProxyInfo);
	STDMETHOD(CreateAccessor)(PCWSTR pcwszURL, AUTHENTICATION_INFO *pAuthenticationInfo, INCREMENTAL_ACCESS_INFO *pIncrementalAccessInfo, ITEM_INFO *pItemInfo, __deref_out IUrlAccessor **ppAccessor);
	STDMETHOD(CloseAccessor)(IUrlAccessor *pAccessor);
	STDMETHOD(ShutDown)(void);

	// ISearchProtocol2

	STDMETHOD(CreateAccessorEx)(PCWSTR pcwszURL, AUTHENTICATION_INFO *pAuthenticationInfo, INCREMENTAL_ACCESS_INFO *pIncrementalAccessInfo, ITEM_INFO *pItemInfo, const BLOB *pUserData, __deref_out IUrlAccessor **ppAccessor);

	// ISearchProtocolThreadContext

	STDMETHOD(ThreadInit)(void);
	STDMETHOD(ThreadShutdown)(void);
	STDMETHOD(ThreadIdle)(DWORD dwTimeElaspedSinceLastCallInMS);

	// IInternetProtocol

	STDMETHOD(Abort)(HRESULT hrReason, DWORD dwOptions);
	STDMETHOD(Continue)(PROTOCOLDATA *pProtocolData);
	STDMETHOD(Resume)();
	STDMETHOD(Start)(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved);
	STDMETHOD(Suspend)();
	STDMETHOD(Terminate)(DWORD dwOptions);
	STDMETHOD(LockRequest)(DWORD dwOptions);
	STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead);
	STDMETHOD(Seek)(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition);
	STDMETHOD(UnlockRequest)();

	// IInternetProtocolInfo

	STDMETHOD(CombineUrl)(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved);
	STDMETHOD(CompareUrl)(LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags);
	STDMETHOD(ParseUrl)(LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved);
	STDMETHOD(QueryInfo)(LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved);

	//// IShellFolder
	//STDMETHOD(ParseDisplayName)( 
	//	/* [unique][in] */ __RPC__in_opt HWND hwnd,
	//	/* [unique][in] */ __RPC__in_opt IBindCtx *pbc,
	//	/* [string][in] */ __RPC__in_string LPWSTR pszDisplayName,
	//	/* [annotation][unique][out][in] */ __reserved  ULONG *pchEaten,
	//	/* [out] */ __RPC__deref_out_opt PIDLIST_RELATIVE *ppidl,
	//	/* [unique][out][in] */ __RPC__inout_opt ULONG *pdwAttributes);

	//STDMETHOD(EnumObjects)( 
	//	/* [unique][in] */ __RPC__in_opt HWND hwnd,
	//	/* [in] */ SHCONTF grfFlags,
	//	/* [out] */ __RPC__deref_out_opt IEnumIDList **ppenumIDList);

	//STDMETHOD(BindToObject)( 
	//	/* [in] */ __RPC__in PCUIDLIST_RELATIVE pidl,
	//	/* [unique][in] */ __RPC__in_opt IBindCtx *pbc,
	//	/* [in] */ __RPC__in REFIID riid,
	//	/* [iid_is][out] */ __RPC__deref_out_opt void **ppv);

	//STDMETHOD(BindToStorage)( 
	//	/* [in] */ __RPC__in PCUIDLIST_RELATIVE pidl,
	//	/* [unique][in] */ __RPC__in_opt IBindCtx *pbc,
	//	/* [in] */ __RPC__in REFIID riid,
	//	/* [iid_is][out] */ __RPC__deref_out_opt void **ppv);

	//STDMETHOD(CompareIDs)( 
	//	/* [in] */ LPARAM lParam,
	//	/* [in] */ __RPC__in PCUIDLIST_RELATIVE pidl1,
	//	/* [in] */ __RPC__in PCUIDLIST_RELATIVE pidl2);

	//STDMETHOD(CreateViewObject)( 
	//	/* [unique][in] */ __RPC__in_opt HWND hwndOwner,
	//	/* [in] */ __RPC__in REFIID riid,
	//	/* [iid_is][out] */ __RPC__deref_out_opt void **ppv);

	//STDMETHOD(GetAttributesOf)( 
	//	/* [in] */ UINT cidl,
	//	/* [unique][size_is][in] */ __RPC__in_ecount_full_opt(cidl) PCUITEMID_CHILD_ARRAY apidl,
	//	/* [out][in] */ __RPC__inout SFGAOF *rgfInOut);

	//STDMETHOD(GetUIObjectOf)( 
	//	/* [unique][in] */ __RPC__in_opt HWND hwndOwner,
	//	/* [in] */ UINT cidl,
	//	/* [unique][size_is][in] */ __RPC__in_ecount_full_opt(cidl) PCUITEMID_CHILD_ARRAY apidl,
	//	/* [in] */ __RPC__in REFIID riid,
	//	/* [annotation][unique][out][in] */ __reserved  UINT *rgfReserved,
	//	/* [iid_is][out] */ __RPC__deref_out_opt void **ppv);

	//STDMETHOD(GetDisplayNameOf)( 
	//	/* [unique][in] */ __RPC__in_opt PCUITEMID_CHILD pidl,
	//	/* [in] */ SHGDNF uFlags,
	//	/* [out] */ __RPC__out STRRET *pName);

	//STDMETHOD(SetNameOf)( 
	//	/* [annotation][unique][in] */ __in_opt  HWND hwnd,
	//	/* [annotation][in] */ __in  PCUITEMID_CHILD pidl,
	//	/* [annotation][string][in] */ __in  LPCWSTR pszName,
	//	/* [annotation][in] */ __in  SHGDNF uFlags,
	//	/* [annotation][out] */ __deref_opt_out  PITEMID_CHILD *ppidlOut);

	//// IPersist
	//STDMETHOD(GetClassID)( 
	//	/* [out] */ __RPC__out CLSID *pClassID);

	//// IPersistFolder
	//STDMETHOD(Initialize)( 
	//	/* [in] */ __RPC__in PCIDLIST_ABSOLUTE pidl);

	//// IDelegateFolder
	//STDMETHOD(SetItemAlloc)( 
	//	/* [annotation][in] */ __in  IMalloc *pmalloc);
};

OBJECT_ENTRY_AUTO(__uuidof(MirandaProtocol), CMirandaProtocol)
